using System;
using System.Collections;

namespace JamesKovacs.Examples.ContractManager {
	/// <summary>
	/// Contract details the sale of a product.
	/// </summary>
	public class Contract {
		#region Constructors
		/// <summary>
		/// Creates a new <see cref="Contract"/> instance.
		/// </summary>
		/// <param name="product">Product.</param>
		/// <param name="revenue">Revenue.</param>
		/// <param name="signingDate">Signing date.</param>
		public Contract(Product product, Money revenue, DateTime signingDate) {
			m_id = Guid.NewGuid();
			m_product = product;
			m_revenue = revenue;
			m_signingDate = signingDate;
			m_revenueRecognitions = new ArrayList();
		}
		#endregion

		#region Public properties
		/// <summary>
		/// Gets the id.
		/// </summary>
		/// <value>Unique identifier.</value>
		public Guid Id {
			get {
				return m_id;
			}
		}

		/// <summary>
		/// Gets the contract's <see cref="Product"/>.
		/// </summary>
		/// <value><see cref="Product"/> instance related to </value>
		public Product ContractProduct {
			get {
				return m_product;
			}
		}

		/// <summary>
		/// Gets the revenue.
		/// </summary>
		/// <value>Amount of revenue.</value>
		public Money Revenue {
			get {
				return m_revenue;
			}
		}

		/// <summary>
		/// Gets the signing date.
		/// </summary>
		/// <value><see cref="DateTime"/> on which contract was signed.</value>
		public DateTime SigningDate {
			get {
				return m_signingDate;
			}
		}
		#endregion

		#region Public methods
		/// <summary>
		/// Calculates the recognized revenue.
		/// </summary>
		/// <param name="asOf">Date as of which to calculate the revenue.</param>
		/// <returns>Amount of revenue recognized as of the date.</returns>
		public Money CalculateRecognizedRevenue(DateTime asOf) {
			Money result = new Money(0M);
			foreach(RevenueRecognition revRec in m_revenueRecognitions) {
				if(revRec.IsRecognizableBy(asOf)) {
					result += revRec.Amount;
				}
			}
			return result;
		}

		/// <summary>
		/// Adds the revenue recognition.
		/// </summary>
		/// <param name="revenueRecognition">Revenue recognition.</param>
		public void AddRevenueRecognition(RevenueRecognition revenueRecognition) {
			m_revenueRecognitions.Add(revenueRecognition);
		}

		/// <summary>
		/// Creates the <see cref="RevenueRecognition"/> instances based on the <see cref="Product"/>'s <see cref="RecognitionStrategy"/>.
		/// </summary>
		public void CalculateRecognitions() {
			m_product.CalculateRevenueRecognitions(this);
		}
		#endregion

		#region Private fields
		private ArrayList m_revenueRecognitions;
		private Product m_product;
		private Money m_revenue;
		private DateTime m_signingDate;
		private Guid m_id;
		#endregion
	}
}
